package com.genericdevice.platform.core.menu;

import android.app.Activity;
import android.content.res.XmlResourceParser;
import com.genericdevice.platform.core.logging.LoggerHelper;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Xilent on 18.05.2014.
 */
public class OptionsMenuConfig {
    private static final String RESOURCES_TAG = "resources";
    private static final String ITEM_TAG = "item";
    private static final String ACTION_TAG = "action";
    private static final String PARAMS_TAG = "param";
    private static final String ID_ATTR = "id";
    private static final String NAME_ATTR = "name";
    private static final String VALUE_ATTR = "value";
    private static final String ACTIVITY_KEY = "activity";
    private static final String ACTIVITY_PARAMS_KEY = "activityParams";
    private static final String EVENT_KEY = "event";

    private static LoggerHelper LOGGER = LoggerHelper.getInstance();

    private static Map<Integer, OptionsMenuConfig> CONFIGS = new HashMap<Integer, OptionsMenuConfig>();

    private Integer resourceId;
    private Class ids;
    private Activity activity;
    private Map<Integer, Map<String, String>> config = new HashMap<Integer, Map<String, String>>();

    public static OptionsMenuConfig getInstance(Integer resourceId, Class ids) {
        OptionsMenuConfig instance = CONFIGS.get(resourceId);
        if (instance == null) {
            instance = new OptionsMenuConfig(resourceId, ids);
            CONFIGS.put(resourceId, instance);
        }

        return instance;
    }

    private OptionsMenuConfig(Integer resourceId, Class ids) {
        this.resourceId = resourceId;
        this.ids = ids;
    }

    public void setActivity(Activity activity) {
        this.activity = activity;
    }

    public void init() {
        try {
            parseXml();
        } catch (Exception e) {
            LOGGER.error("Can not parse option resource file", e);
        }
    }

    public Integer getResourceId() {
        return resourceId;
    }

    public void setIds(Class ids) {
        this.ids = ids;
    }

    public String getActivity(Integer itemId) {
        Map<String, String> item = config.get(itemId);
        if (item == null)
            return null;

        return item.get(ACTIVITY_KEY);
    }

    public String getEvent(Integer itemId) {
        Map<String, String> item = config.get(itemId);
        if (item == null)
            return null;

        return item.get(EVENT_KEY);
    }

    public Map<String, String> getParams(Integer itemId) {
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String> item = config.get(itemId);
        if (item == null)
            return params;

        for (Map.Entry<String, String> entry : item.entrySet()) {
            String key = entry.getKey();
            if (!key.equals(ACTIVITY_KEY) && !key.equals(EVENT_KEY)) {
                params.put(key, entry.getValue());
            }
        }

        return params;
    }

    private void parseXml() throws XmlPullParserException, IOException, NoSuchFieldException, IllegalAccessException {
        XmlResourceParser xml = activity.getResources().getXml(resourceId);

        if (xml == null) {
            LOGGER.error("Can not load xml resource with id: " + resourceId, null);
            return;
        }

        int eventType = xml.getEventType();
        String tagName;
        do {
            if (eventType == XmlPullParser.START_TAG) {
                tagName = xml.getName();
                if (tagName.equals(RESOURCES_TAG)) {
                    // Go to next tag
                    eventType = xml.next();
                    break;
                }

                throw new RuntimeException("Expecting resource, got " + tagName);
            }
            eventType = xml.next();
        } while (eventType != XmlPullParser.END_DOCUMENT);

        boolean reachedEndOfMenu = false;

        Integer itemId = null;
        Map<String, String> actions = new HashMap<String, String>();

        while (!reachedEndOfMenu) {
            switch (eventType) {
                case XmlPullParser.START_TAG:
                    tagName = xml.getName();

                    if (tagName.equals(ITEM_TAG)) {
                        String itemIdName = xml.getAttributeValue(null, ID_ATTR);
                        itemId = getItemId(itemIdName);
                    } else if (tagName.equals(ACTION_TAG)) {
                        String name = xml.getAttributeValue(null, NAME_ATTR);
                        if (name.equals(ACTIVITY_KEY))
                            actions.put(ACTIVITY_KEY, xml.getAttributeValue(null, VALUE_ATTR));
                        else if (name.equals(EVENT_KEY)) {
                            actions.put(EVENT_KEY, xml.getAttributeValue(null, VALUE_ATTR));
                        }
                    } else if (tagName.equals(PARAMS_TAG)) {
                        String name = xml.getAttributeValue(null, NAME_ATTR);
                        actions.put(name, xml.getAttributeValue(null, VALUE_ATTR));
                    } else {
                        throw new RuntimeException("Unexpected tag name");
                    }

                    break;

                case XmlPullParser.END_TAG:
                    tagName = xml.getName();
                    if (tagName.equals(RESOURCES_TAG)) {
                        reachedEndOfMenu = true;
                    } else if (tagName.equals(ITEM_TAG)) {
                        config.put(itemId, actions);
                        itemId = null;
                        actions = new HashMap<String, String>();
                    }
                    break;

                case XmlPullParser.END_DOCUMENT:
                    throw new RuntimeException("Unexpected end of document");
            }

            eventType = xml.next();
        }
    }

    private int getItemId(String name) throws NoSuchFieldException, IllegalAccessException {
        return ids.getField(name).getInt(null);
    }
}
